package org.brisling.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;





/**
 * reflect tool for get and set data to entity object and PropertysetItem 
 * @author wang
 *
 */
public class ReflectDataUtil {
	
	static HashMap<String,Method> _methodMap =new HashMap<String,Method>();
	
	public ReflectDataUtil(){};
	
	
	@SuppressWarnings("rawtypes")
	public static Object setData2Obj(Object targetObj,HashMap map){
		
		if(targetObj!=null){
			
			Method[] _method = targetObj.getClass().getDeclaredMethods();
			
			_methodMap.clear();
			//反射目标对象所有method，存入map待用
			if(_method!=null&&_method.length>0){
				for(int i=0;i<_method.length;i++){
					_methodMap.put(_method[i].getName(), _method[i]);
				}
			}
			
			if(map!=null){
		
				for(Iterator ite= map.entrySet().iterator();ite.hasNext();){
					Map.Entry entry = (Map.Entry) ite.next();
					setDataToField(targetObj,(String) entry.getKey(),entry.getValue());
				}
			}
		}
		
		return targetObj;
	}
	/**
	 * invode targetObj set method then set dataObj to targetObje declared fieldName field 
	 * @param targetObj	Object will invoke set method
	 * @param fieldName declared field name
	 * @param dataObj	set method param 
	 * @return targetObj that invoked set method
	 */
	@SuppressWarnings("rawtypes")
	public static Object setDataToField(Object targetObj,String fieldName,Object dataObj){
		
				
		String methodName = "set"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
		
		if(_methodMap.containsKey(methodName)){
			
			Method method = _methodMap.get(methodName);
			Class clazz = (method.getParameterTypes())[0];			
			
			String str = clazz.getName();			
			
			try {
				
				method = targetObj.getClass().getDeclaredMethod(methodName, clazz);
				
			
				switch(str){
				case "java.lang.Integer"
					:method.invoke(targetObj, Integer.parseInt(dataObj.toString()));
					break;
				case "java.lang.Long"	
					:method.invoke(targetObj, Long.parseLong(dataObj.toString()));
					break;
				case "java.lang.String"
					:method.invoke(targetObj, dataObj);
					break;
				case "java.util.Date"
					:method.invoke(targetObj, DateUtil.JsonStr2Date(dataObj.toString()));
				};
				
				
				
			} catch (NoSuchMethodException | SecurityException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return targetObj;
	}
	
	
	/**
	 * get targetObject declared special fieldName's data type
	 * @param fieldName	declared field name
	 * @param targetObj	reflect Object
	 * @return 
	 */
	@SuppressWarnings({ "rawtypes", "unused" })
	private static Class getFieldClass(String fieldName,Object targetObj){
		Class clazz = null;
		
		try {
			clazz = targetObj.getClass().getDeclaredField(fieldName).getType();
		} catch (NoSuchFieldException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (SecurityException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}				
		
		return clazz;
	}
	
	@SuppressWarnings("unused")
	private static Object getFieldValue(String fieldName,Object targetObj){
		
		Object retObj = null;
		String method_name = "get"+fieldName.substring(0,1).toUpperCase()+fieldName.substring(1);
		
		Method method = null;
		Class<?>[] clazz = null;
		Class<?> _clazz = null;
		try {
			method = targetObj.getClass().getDeclaredMethod(method_name, clazz);
			retObj= method.invoke(targetObj, _clazz);
		} catch (NoSuchMethodException | SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		return retObj;
	}
	
	

}
